import {ElMessage} from "element-plus";

let socket = null; // 实例对象
let lockReconnect = false // 是否真正建立连接
let timeout = 60 * 1000 // 一分钟一次心跳
let timeoutObj = null // 心跳倒计时
let serverTimeoutObj = null // 服务心跳倒计时
let timeoutNum = null // 断开重连倒计时

// 初始化websocket, 使用时传入token
const initWebsocket = async (token) => {
    if ("WebSocket" in window) {
        const wsUrl = 'ws://localhost:8000/ws/' + token
        socket = new WebSocket(wsUrl)  // websocket连接,连接后后台返回一个socket实例
        socket.onerror = webSocketOnError   // 发生错误的回调函数
        socket.onmessage = webSocketOnMessage  // 接收到后台信息的函数
        socket.onclose = webSocketOnClose  // 关闭连接的函数
        socket.onopen = openWebSocket   // 打开连接的函数
    } else {
        ElMessage.error("您的浏览器不支持webSocket，请更换浏览器")
    }
}

// 建立打开连接
export const openWebSocket = (e) => {
    start();
}

export const start = () => {
    // 开启心跳
    timeoutObj && clearTimeout(timeoutObj)
    serverTimeoutObj && clearTimeout(serverTimeoutObj)
    timeoutObj = setTimeout(function (){
        // 这里发送一个心跳，后端收到后，返回一个心跳消息
        if (socket.readyState === 1) {
           // 如果连接正常
           // socket.send(JSON.stringify({ type: 'heartbeat' }))
        } else {
            // 否则重连
            reconnect()
        }
        serverTimeoutObj = setTimeout(function (){
            // 超时关闭
            socket.close()
        }, timeout)
    }, timeout)
}

// 重新连接
export const reconnect = () => {
    if (lockReconnect) {

    }
    lockReconnect = true
    timeoutNum && clearTimeout(timeoutNum)
    timeoutNum = setTimeout(function (){
        // 新连接
        initWebsocket().then(r => {

        })
        lockReconnect = false
    }, 10000)
}

// 重置心跳
export const reset = () => {
    // 清除时间
    clearTimeout(timeoutObj)
    clearTimeout(serverTimeoutObj)
    // 重启心跳
    start()
}

// 发生错误执行所执行的具体函数
export const webSocketOnError = (e) => {
    reconnect()
}

export const sendMessage = (e) => {
    socket.send(e)
}

export const webSocketOnClose = () => {
    socket.close()
}

// 角色判断 admin_user : code_user,拿到token判断登录
export const webSocketOnMessage = (e) => {
    // windows自定义事件  // 监听onmessageWs的事件，并进行处理
    const message = JSON.parse(e.data);
    // 分发消息时保留原始数据类型
    window.dispatchEvent(
        new CustomEvent("onmessageWs", {
            detail: {
                data:message
            },
        })
    )
    reset(); // 重置心跳
}

// 断开连接
export const close = () => {
    // websocket对象也有发送和关闭的俩个方法，只需要在自定义方法中分别调用send()和close()即可实现
    socket.close()
}

// 对外暴露需要的方法
export  default {initWebsocket, webSocketOnMessage, close, sendMessage}